home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Personal Computer World 2009 February
/
PCWFEB09.iso
/
Software
/
Resources
/
Chat & Communication
/
PeerAware 1.03
/
PeerAware-Setup.exe
/
Html
/
scripts
/
svgrenderer.js
< prev
next >
Wrap
Text File
|
2008-01-06
|
57KB
|
2,019 lines
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Cumulate Draw SVG Renderer.
*
* The Initial Developer of the Original Code is
* Cumulate Labs Inc.
* Portions created by Cumulate Labs Inc. are Copyright (C) 2006-2007
* Cumulate Labs Inc. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/*----------------------------------------------------------------------------
SVGRENDERER 0.1
SVG Renderer For cumulate draw (http://www.cumulatelabs.com)
History:
2006-10-19 | created
*/
/**********************************BEGIN INITIALIZATION FUNCTIONS******************************/
function SVGRenderer() {
this.base = AbstractRenderer;
this.svgRoot = null;
}
SVGRenderer.prototype = new AbstractRenderer;
SVGRenderer.prototype.init = function(elem) {
this.MAX_HEIGHT=2000;
this.MAX_WIDTH=2000;
this.COORD_X=1000;//ALL shapes are defined in 1000x1000 coord space
this.COORD_Y=1000;
this.CONNECTOR_TAG="svg:connector";
this.TEXT_TEMPLATE_PREFIX="text:template";
this.LINE_DELIMITER="\n";
this.GRADIENT_PREFIX="GRADIENT";
this.MARKER_BEGIN_PREFIX="MARKER_START";
this.MARKER_END_PREFIX="MARKER_END";
this.EXTENSION='fmd';
this.TYPE="SVG";
this.container = elem;
this.svgNamespace = 'http://www.w3.org/2000/svg';
this.cumulateNamespace="urn:schemas-cumulatelabs-com:svg";
this.xmlNamespace="http://www.w3.org/2001/xml";
this.svgRoot = this.container.ownerDocument.createElementNS(this.svgNamespace, "svg");
this.svgRoot.setAttribute("xml:space","preserve");
this.LONG_DASH="7,3";
this.SHORT_DASH="4,3";
var shadow=this.loadShape('shadow','defs');
this.svgRoot.style.position="absolute";
this.svgRoot.style.zIndex=10;
this.svgRoot.setAttributeNS(null, 'x','0px');
this.svgRoot.setAttributeNS(null, 'y', '0px');
this.svgRoot.setAttributeNS(null, 'width',this.MAX_WIDTH+'px');
this.svgRoot.setAttributeNS(null, 'height',this.MAX_HEIGHT+'px');
var firstChild=this.container.firstChild;
this.svgRoot.style.MozUserSelect = 'none';
this.minIndex=200;
this.maxIndex=200;
this.container.insertBefore(this.svgRoot,firstChild);
this.svgRoot.appendChild(shadow);
}
/****************************************************END INITIALIZATION FUNCTIONS**************************************/
/**
*return the current bounds of the shape
**/
SVGRenderer.prototype.bounds = function(shape) {
if(!shape)return
var rect = { x:0, y:0, width:0, height: 0,rotation:0,x2:0,y2:0,id:0,type:"",controlX:0,controlY:0,controlX2:0,controlY2:0 };
rect['id']=shape.getAttributeNS(null,"id");
if(this.isConnector(shape))
{
rect['x']=this.getConnectorFromX(shape);
rect['y']=this.getConnectorFromY(shape);
rect['x2']=this.getConnectorToX(shape);
rect['y2']=this.getConnectorToY(shape);
rect['type']=this.getConnectorType(shape);
if(rect.type=='curve-line'){
var obj1=this.getControl1(shape);
var obj2=this.getControl2(shape);
rect['controlX']=obj1.x;
rect['controlY']=obj1.y;
rect['controlX2']=obj2.x;
rect['controlY2']=obj2.y;
}
}
else{
rect['rotation']=this.getRotation(shape);
if(!rect['rotation'])
rect['rotation']=0;
rect['x'] = this.getX(shape);
rect['y'] = this.getY(shape);
rect['width'] = this.getWidth(shape);
rect['height'] = this.getHeight(shape);
}
return rect;
}
/*************************BEGIN SHAPE CREATION FUNCTIONS****************************/
/**
*load an xml shape for creation-
*TODO we will have to add some error handling later on
*/
SVGRenderer.prototype.loadShape=function(shapeID,retrieveTag){
objValidXMLFile=this.loadXML("shapes/svg/"+shapeID+".xml");
var nodeList=objValidXMLFile.getElementsByTagName(retrieveTag);
if(retrieveTag){
var node=nodeList[0];
return node;
}
}
SVGRenderer.prototype.loadXML=function(path){
var objValidXMLFile = document.implementation.createDocument(null, null, null);
objValidXMLFile.async=false;
objValidXMLFile.load(path);
return objValidXMLFile;
}
/**
* create a line shape
**/
SVGRenderer.prototype.createLine=function(shape,lineColor,lineWidth,left,top,lineStyle){
var svg=this.loadShape(shape,"g");
this.svgRoot.appendChild(svg);
if(shape=='line'||shape=='curve-line'){
this.setLineFrom(svg,left,top);
this.setLineTo(svg,left,top);
}
if(shape=='curve-line'){
this.setControl1(svg,left,top);
this.setControl2(svg,left,top);
}
var markers=this.getMarkers(svg);
markers[0].id=this.MARKER_BEGIN_PREFIX+createUUID();
markers[1].id=this.MARKER_END_PREFIX+createUUID();
this.setZIndex(svg,this.maxIndex++);
return svg;
}
/**
*all svg shapes are in the format g/svg/path in addition filters for linear gradient, line stroke may be added
**/
SVGRenderer.prototype.create = function(shape, fillColor, lineColor, lineWidth, left, top, width, height) {
var svg=this.loadShape(shape,"g");
this.svgRoot.appendChild(svg);
this.setX(svg,left);
this.setY(svg,top);
this.setWidth(svg,width);
this.setHeight(svg,height);
this.setZIndex(svg,this.maxIndex++);
this.fixLinearGradientID(svg);
//now fix the shape to match its linear gradient!
// var isGradient=this.getLinearGradient(svg);
// if(isGradient)this.setLinearGradient(svg,true);
// this.setFillColor(svg,this.getFillColor(svg));
return svg;
};
/**
*utility function to create and element based on namespace constants
**/
SVGRenderer.prototype.createElement=function(elementTag,namespace){
if(namespace=='CUMULATE_LABS'){
return this.container.ownerDocument.createElementNS(this.cumulateNamespace,elementTag);
}
else{
return this.container.ownerDocument.createElementNS(this.svgNamespace,elementTag);
}
}
/**
* a utitlity function to return an attribute in IE specific manner,assumes that element
* is not null!
**/
SVGRenderer.prototype.getAttribute=function(element,attribute){
return element.getAttributeNS(null,attribute);
}
/**
* clone the node
**/
SVGRenderer.prototype.copy=function(shape){
if(!shape)return null;
return shape.cloneNode(true);
}
/**
*add the cloned node
**/
SVGRenderer.prototype.paste=function(shape){
if(!shape)return;
var node=shape;
node.id='shape:' + createUUID();
var svg=node.getElementsByTagName("svg");
if(svg.length>0)
svg.item(0).id='shape:'+createUUID();
var text=node.getElementsByTagName("text")
for(var i=0;i<text.length;i++){
var textItem=text.item(i);
if(textItem.id.indexOf(this.TEXT_TEMPLATE_PREFIX)>=0){
textItem.id=this.TEXT_TEMPLATE_PREFIX+node.id;
}
}
if(!this.isConnector(node)){
var x=this.getX(node);
var y=this.getY(node);
this.setX(node,(x*1)+10);
this.setY(node,(y*1)+10);
//update the gradient;
this.fixLinearGradientID(node);
}
if(this.isConnector(node)){
var markers=this.getMarkers(node);
markers[0].id=this.MARKER_BEGIN_PREFIX+createUUID();
markers[1].id=this.MARKER_END_PREFIX+createUUID();
var lineStyle=this.getLineStyle(node);
this.setLineStyle(node,lineStyle);
}
//now null any connections
var connectList=node.getElementsByTagName("connection");
var array=new Array();
for(var i=0;i<connectList.length;i++){
//if its a line emtpy it
if(this.isConnector(node)){
connectList.item(i).setAttribute("shapeid","xx");
connectList.item(i).setAttribute("shapepoint","-1");
}
//if its a shape remove it!
else{
array[i]=connectList.item(i);
}
}
for(var i=0;i<array.length;i++){
this.remove(array[i]);
}
//append automatically brings the shape to the front for svg
this.svgRoot.appendChild(node);
return node;
}
/*************************END SHAPE CREATION FUNCTIONS****************************/
/**
*indicate if a shape is a connector
**/
SVGRenderer.prototype.isConnector=function(shape){
if(shape)
return (shape.getElementsByTagName("connector").length>0);
else
return false;
}
/*************************ZINDEX FUNCTIONS************************/
/**
*set the shape ZIndex, this method does nothing since svg does not support zindexes
*@see http://wiki.svg.org/Rendering_Order
*@param shape
*@param zIndex;
**/
SVGRenderer.prototype.setZIndex=function(shape,zIndex){
if(shape){
shape.setAttributeNS(null,"z-index",zIndex);
}
}
/**
*get the shape zIndex, this method is just informational, since svg does not support zindexes
*@see http://wiki.svg.org/Rendering_Order
*@param shape
*@return zIndex
**/
SVGRenderer.prototype.getZIndex=function(shape){
if(shape)
return shape.getAttributeNS(null,"z-index");
}
/**
* send to back
*@param the shape
**/
SVGRenderer.prototype.sendToBack=function(shape){
if(shape){
var node =shape.cloneNode(true);
this.remove(shape);
this.svgRoot.insertBefore(node,this.svgRoot.firstChild);
this.setZIndex(node,this.minIndex--);
return node;
}
}
/**
* Bring to Front
*@param the shape
**/
SVGRenderer.prototype.bringToFront=function(shape){
if(shape){
var node =shape.cloneNode(true);
this.remove(shape);
this.svgRoot.appendChild(node);
this.setZIndex(node,this.maxIndex++);
return node;
}
}
/*************************LINE FUNCTIONS***********************/
/**
*set the line from
**/
SVGRenderer.prototype.setLineFrom=function(shape,fromX,fromY){
var subject=this.getShapeSubject(shape);
var type=this.getConnectorType(shape);
if(type=='line'){
subject.setAttributeNS(null,"x1",fromX);
subject.setAttributeNS(null,"y1",fromY);
}
else if(type=='curve-line'){
var path=subject.pathSegList;
var pathItem=path.getItem(0);
pathItem.x=fromX;
pathItem.y=fromY;
}
}
/**
*set the line to
**/
SVGRenderer.prototype.setLineTo=function(shape,toX,toY){
var subject=this.getShapeSubject(shape);
var type=this.getConnectorType(shape);
if(type=='line'){
subject.setAttributeNS(null,"x2",toX);
subject.setAttributeNS(null,"y2",toY);
}
else if(type=='curve-line'){
var path=subject.pathSegList;
var pathItem=path.getItem(1);
pathItem.x=toX;
pathItem.y=toY;
}
}
/**
* set control point 1
**/
SVGRenderer.prototype.setControl1=function(shape,toX,toY){
var subject=this.getShapeSubject(shape);
var path=subject.pathSegList;
var pathItem=path.getItem(1);
pathItem.x1=toX;
pathItem.y1=toY;
}
/**
* set control point 1
**/
SVGRenderer.prototype.getControl1=function(shape){
var subject=this.getShapeSubject(shape);
var path=subject.pathSegList;
var pathItem=path.getItem(1);
var obj=new Object();
obj.x=pathItem.x1;
obj.y=pathItem.y1;
return obj;
}
/**
* set control point 1
**/
SVGRenderer.prototype.setControl2=function(shape,toX,toY){
var subject=this.getShapeSubject(shape);
var path=subject.pathSegList;
var pathItem=path.getItem(1);
pathItem.x2=toX;
pathItem.y2=toY;
}
/**
* set control point 1
**/
SVGRenderer.prototype.getControl2=function(shape){
var subject=this.getShapeSubject(shape);
var path=subject.pathSegList;
var pathItem=path.getItem(1);
var obj=new Object();
obj.x=pathItem.x2;
obj.y=pathItem.y2;
return obj;
}
/**
*simply for compatibility reasons, the vml version converts pixels to points in this method,
*svg version does not need that
**/
SVGRenderer.prototype.moveLinePoint=function(shape,toX,toY,isFrom){
this.moveLine(shape,toX,toY,isFrom);
}
/**
*move line or polyline
**/
SVGRenderer.prototype.moveLine=function(shape,toX,toY, isFrom){
if(!shape||!this.isConnector(shape)){
return;
}
var type=this.getConnectorType(shape);
if(type=='line'||type=='curve-line'){
if(isFrom){
this.setLineFrom(shape,toX,toY);
}
else{
this.setLineTo(shape,toX,toY);
}
}
else{
var subject =shape.getElementsByTagName("polyline")[0];
var points=subject.points;
var length=points.numberOfItems;
if(isFrom){
var x=points.getItem(length-1).x;
var y=points.getItem(length-1).y;
this.drawOrthoLine(shape,toX,toY,x,y);
}
else{
var x=points.getItem(0).x;
var y=points.getItem(0).y;
this.drawOrthoLine(shape,x,y,toX,toY);
}
}
}
/**********************************************BEGIN ORTHO-LINE DRAW FUNCTIONS**************************/
/**
* get the segments of the orthogonal connector--get the central segment,
* @return {object} containing x,y,x2,y2
*/
SVGRenderer.prototype.getOrthoLineCenterSegment=function(shape){
//debugger;
var obj=new Object();
var points=this.getShapeSubject(shape).points;
//get the center point
var centerPoint=Math.round(points.numberOfItems/2-1);
var center=points.getItem(centerPoint);
var before=points.getItem(centerPoint-1);
var after=points.getItem(centerPoint+1);
var distanceA=((center.y-before.y)*(center.y-before.y))+((center.x-before.x)*(center.x-before.x));
var distanceB=((center.y-after.y)*(center.y-after.y))+((center.x-after.x)*(center.x-after.x));
var referencePoint=distanceA>distanceB?before:after;
obj.x=referencePoint.x;
obj.y=referencePoint.y;
obj.x2=center.x;
obj.y2=center.y;
return obj;
}
/*
*special method to draw orthogonal lines. first calculate the horizontal distance, then calculate the vertical distance,
* if horizontal< vertical, split horizontal in 1/2 and vice versa, set this in the shape
*/
SVGRenderer.prototype.drawOrthoLine= function(shape,fromX,fromY,toX,toY){
var path=this.calculateOrthoLinePath(shape,fromX,fromY,toX,toY);
var polyline=this.getShapeSubject(shape);
polyline.setAttributeNS(null,"points",path);
}
/************************************************END ORTHO-LINE DRAW FUNCTIONS************************/
/**
*display all connection points, this will take the c:connection-point coordinates defined in 1000,1000 space
* and scale them to current coordinate system
**/
SVGRenderer.prototype.showConnectionPoints=function(shape){
if(!shape)return;
//debugger;
var rect=this.bounds(shape);
var rotation=rect['rotation'];
if(!rotation)rotation=0;
this.remove($('active-shape-tracker'));
var doc=this.container.ownerDocument;
var group=doc.createElementNS(this.svgNamespace,"g");
var svg=doc.createElementNS(this.svgNamespace,"svg");
group.appendChild(svg);
group.style.position="ABSOLUTE";
group.style.zIndex=this.maxIndex+1;
var centerX=parseInt(rect['x'])+parseInt(rect['width']/2);
var centerY=parseInt(rect['y'])+parseInt(rect['height']/2);
group.setAttributeNS(null,"transform","rotate("+rotation+","+centerX+","+centerY+")");
group.style.zIndex=(shape.style.zIndex*1)+1;
group.id='active-shape-tracker';
var width=rect['width'];
var height=rect['height'];
var nodeList=shape.getElementsByTagName("connection-point");
for(var i=0;i<nodeList.length;i++){
var node=nodeList.item(i);
var oval=doc.createElementNS(this.svgNamespace,"circle");
var x=parseInt(rect['x'])+(node.getAttribute('x')*width/this.COORD_X);
var y=parseInt(rect['y'])+(node.getAttribute('y')*height/this.COORD_Y);
oval.setAttributeNS(null,'fill',"red");
oval.setAttributeNS(null,'stroke',"black");
oval.style.position="ABSOLUTE";
oval.setAttributeNS(null,"cx",x);
oval.setAttributeNS(null,"cy",y);
oval.setAttributeNS(null,"r","3");
svg.appendChild(oval);
}
this.svgRoot.appendChild(group);
}
/*
*connectLine, first calculate if the line end matches a connection point
* if yes then add an entry to ensure that line and shape are connected
**/
SVGRenderer.prototype.connectLine=function(shape,connector,toOrFrom){
if(!connector)return;
//first disconnect the line
this.disconnectLineFromShape(connector,toOrFrom);
if(!shape)return;
//get the line coordinates in pixels
var screenxdpi=screen.logicalXDPI / 72;
var x=0;
var y=0;
var type=this.getConnectorType(connector);
if(type=='line'||type=='curve-line'){
var line=this.getShapeSubject(connector);
if(toOrFrom=="from"){
x=this.getConnectorFromX(connector);
y=this.getConnectorFromY(connector);
}
else{
x=this.getConnectorToX(connector);
y=this.getConnectorToY(connector);
}
}
else{
if(toOrFrom=="from"){
x=this.getShapeSubject(connector).points.getItem(0).x;
y=this.getShapeSubject(connector).points.getItem(0).y;
}
else{
var length=this.getShapeSubject(connector).points.numberOfItems;
if(length==0)return;
x=this.getShapeSubject(connector).points.getItem(length-1).x;
y=this.getShapeSubject(connector).points.getItem(length-1).y;
}
}
//now get the shape center
var rect=this.bounds(shape);
var centerX=parseInt(rect['x']*1)+parseInt(rect['width']/2);
var centerY=parseInt(rect['y']*1)+(rect['height']/2);
//get the rotation
var rotation=rect['rotation'];
if(!rotation)rotation=0;
//get the shape coordinate size, hardcode for now
var connectionList=shape.getElementsByTagName("connection-point");
for(var i=0;i<connectionList.length;i++){
var node=connectionList.item(i);
//for each connection point get its(unrotated) pixel location
var conX=(rect['x']*1)+((node.getAttributeNS(null,"x")/this.COORD_X)*rect['width']);
var conY=(rect['y']*1)+((node.getAttributeNS(null,"y")/this.COORD_Y)*rect['height']);
//now translate the center to the origin
conX=conX-centerX;
conY=conY-centerY;
//now rotate and translate back
var finalX=((conX*Math.cos((Math.PI/180)*(rotation)))-(conY*Math.sin((Math.PI/180)*(rotation)))*1)+(centerX*1);
var finalY=((conX*Math.sin((Math.PI/180)*(rotation)))+(conY*Math.cos((Math.PI/180)*(rotation)))*1)+(centerY*1);
if(x>(finalX-4)&&x<((finalX*1)+4)&&y>(finalY-4)&&y<((finalY*1)+4)){
this.connectLineToShape(shape,connector,toOrFrom,node,i);
var isFrom=(toOrFrom=="from")?true:false;
this.moveLine(connector,finalX,finalY,isFrom);
$('help').innerHTML="Connected line to shape";
//no need to go on, we found our connection point
return;
}
}
}
/******************************END LINE FUNCTIONS********************************/
/*******************************BEGIN SHAPE ATTRIBUTE GETTERS AND SETTERS************/
/**
*return the type of this connector
**/
SVGRenderer.prototype.getConnectorType=function(shape){
return shape.getAttributeNS(null,"type");
}
/**
*get from x for a valid connector
**/
SVGRenderer.prototype.getConnectorFromX=function(shape){
var x1=null;
var type=this.getConnectorType(shape);
if(type=='line'){
x1=this.getShapeSubject(shape).getAttributeNS(null,"x1");
}
else if(type=='curve-line'){
var subject=this.getShapeSubject(shape);
var path=subject.pathSegList;
x1=path.getItem(0).x;
}
else{
var polyline=this.getShapeSubject(shape);
var points=polyline.points;
if(points.numberOfItems>0)
x1=points.getItem(0).x;
}
return x1;
}
/**
*get from y for a valid connector
**/
SVGRenderer.prototype.getConnectorFromY=function(shape){
var y1=null;
var type=this.getConnectorType(shape);
if(type=='line'){
y1=this.getShapeSubject(shape).getAttributeNS(null,"y1");
}
else if(type=='curve-line'){
var subject=this.getShapeSubject(shape);
var path=subject.pathSegList;
y1=path.getItem(0).y;
}
else{
var polyline=this.getShapeSubject(shape);
var points=polyline.points;
if(points.numberOfItems>0)
y1=points.getItem(0).y;
}
return y1;
}
/**
*get to x for a valid connector
**/
SVGRenderer.prototype.getConnectorToX=function(shape){
var x2=null;
var type=this.getConnectorType(shape);
if(type=='line'){
x2=this.getShapeSubject(shape).getAttributeNS(null,"x2");
}
else if(type=='curve-line'){
var subject=this.getShapeSubject(shape);
var path=subject.pathSegList;
x2=path.getItem(1).x;
}
else{
var polyline=this.getShapeSubject(shape);
var points=polyline.points;
var length=points.numberOfItems;
if(length==0)return null;
x2=points.getItem(length-1).x;
}
return x2;
}
/**
*get to y for a valid connector
**/
SVGRenderer.prototype.getConnectorToY=function(shape){
var y2;
var type=this.getConnectorType(shape);
if(type=='line'){
y2=this.getShapeSubject(shape).getAttributeNS(null,"y2");
}
else if(type=='curve-line'){
var subject=this.getShapeSubject(shape);
var path=subject.pathSegList;
y2=path.getItem(1).y;
}
else{
var polyline=this.getShapeSubject(shape);
var points=polyline.points;
var length=points.numberOfItems;
if(length==0)return;
y2=points.getItem(length-1).y;
}
return y2;
}
/**
*get all shape objects (not including connectors)!
**/
SVGRenderer.prototype.getAllShapes=function(doc){
var nodes=doc.getElementsByTagName("g");
var array=new Array();
for (var i=0;i<nodes.length;i++){
if(!this.isConnector(nodes[i])){
array[array.length]=nodes[i];
}
}
return array;
}
/**
*get all connectors (but not shapes)
**/
SVGRenderer.prototype.getAllConnectors=function(doc){
var nodes=doc.getElementsByTagName("g");
var array=new Array();
for (var i=0;i<nodes.length;i++){
if(this.isConnector(nodes[i])){
array[array.length]=nodes[i];
}
}
return array;
}
/**
*get the stroke width of the shape,
**/
SVGRenderer.prototype.getStrokeWidth=function(shape){
if(!shape)return null;
return this.getShapeSubject(shape).getAttributeNS(null,"stroke-width");
}
/**
*set the stroke width of the shape,
**/
SVGRenderer.prototype.setStrokeWidth=function(shape,width){
this.getShapeSubject(shape).setAttributeNS(null,"stroke-width",width);
}
/**
*get the line color
**/
SVGRenderer.prototype.getLineColor=function(shape){
return this.getShapeSubject(shape).getAttributeNS(null,"stroke");
}
/**
*set the line color
**/
SVGRenderer.prototype.setLineColor=function(shape,value){
if(value=='')value='none';
this.getShapeSubject(shape).setAttributeNS(null, 'stroke', value);
if(this.isConnector(shape)){
var markers=this.getMarkers(shape);
markers[0].setAttributeNS(null,"stroke",value);
markers[0].setAttributeNS(null,"fill",value);
markers[1].setAttributeNS(null,"stroke",value);
markers[1].setAttributeNS(null,"fill",value);
}
}
/**
*get the line color
**/
SVGRenderer.prototype.getOpacity=function(shape){
return this.getShapeSubject(shape).getAttributeNS(null,"fill-opacity");
}
/**
*set the line color
**/
SVGRenderer.prototype.setOpacity=function(shape,value){
if (value != '')
this.getShapeSubject(shape).setAttributeNS(null, 'fill-opacity', value);
}
/**
*get the fill color
**/
SVGRenderer.prototype.getFillColor=function(shape){
if(!this.isConnector(shape)){
if(!this.getLinearGradient(shape))
return this.getShapeSubject(shape).getAttributeNS(null,"fill");
else{
var gradient=this.getLinearGradientElement(shape);
var stop=gradient.getElementsByTagName("stop")[0];
return stop.getAttributeNS(null,"stop-color");
}
}
}
/**
*set the fill color
**/
SVGRenderer.prototype.setFillColor=function(shape,value){
if(this.isConnector(shape))return;
if(value=='') value='none';
var gradient=this.getLinearGradientElement(shape);
var stop=gradient.getElementsByTagName("stop")[0];
stop.setAttributeNS(null,'stop-color',value);
var isGradient=this.getLinearGradient(shape);
if(!isGradient)
this.getShapeSubject(shape).setAttributeNS(null, 'fill', value);
}
/**
* set the shadow for the shape even though it does not work in firefox 1.5, it should work in 2.0 and above
**/
SVGRenderer.prototype.setShadow=function(shape,value){
if (value != 'false')
this.getShapeSubject(shape).setAttributeNS(null, 'filter',"url(#shadow_filter)" );
else
this.getShapeSubject(shape).setAttributeNS(null, 'filter', '');
}
SVGRenderer.prototype.getShadow=function(shape){
if(!shape)return false;
var value=this.getShapeSubject(shape).getAttributeNS(null,'filter');
return(value=="url(#shadow_filter)");
}
/**
*get the actual element that represents the linear gradient
**/
SVGRenderer.prototype.getLinearGradientElement=function(shape){
var gradientList=shape.getElementsByTagName("linearGradient");
if(gradientList.length>0)return gradientList[0];
else return null;
}
/**
* set the linear gradient
**/
SVGRenderer.prototype.setLinearGradient=function(shape, value){
if(this.isConnector(shape))return;
var subject=this.getShapeSubject(shape);
var gradient=this.getLinearGradientElement(shape);
if(value){
var idURL="url(#"+gradient.id+")";
subject.setAttributeNS(null,"fill",idURL);
}
else{
var stop=gradient.getElementsByTagName("stop")[0];
var color=stop.getAttributeNS(null,"stop-color");
subject.setAttributeNS(null,"fill",color);
}
}
/**
*return true or false indicating if the linear gradient is set
**/
SVGRenderer.prototype.getLinearGradient=function(shape){
var subject=this.getShapeSubject(shape);
var gradient=subject.getAttributeNS(null,"fill");
return(gradient.indexOf("url")>=0);
}
/**
* this method is called during create or paste. The idea is to provide unique id's for all
* linear gradients and match them to the corresponding paths
*/
SVGRenderer.prototype.fixLinearGradientID=function(shape){
//first get all the linear gradients
var gradients=shape.getElementsByTagName("linearGradient");
var subShapes=this.getAllSubShapes(shape);
for(var i=0;i<gradients.length;i++){
var gradient=gradients.item(i);
var gradientId=gradient.id;
var newGradientId="Gradient0"+(i+1)+createUUID();
gradient.id=newGradientId;
for(var j=0;j<subShapes.length;j++){
var subShape=subShapes.item(j);
if("url(#"+gradientId+")"==subShape.getAttributeNS(null,"fill")
||"url("+gradientId+")"==subShape.getAttributeNS(null,"fill")){
subShape.setAttributeNS(null,"fill","url(#"+newGradientId+")");
}
}
}
}
/**
*return the marker elements
**/
SVGRenderer.prototype.getMarkers=function(shape){
return shape.getElementsByTagName("marker");
}
/**
*setLineStyle
*@param shape
*@param style: arrow-both, arrow-from, arrow-to, none
**/
SVGRenderer.prototype.setLineStyle=function(shape,style){
if(!this.isConnector(shape))return;
var markers=this.getMarkers(shape);
var idStart="";
var idEnd="";
if(style=='arrow-from'||style=='arrow-both'){
idStart=markers[1].id;
}
if(style=='arrow-to'||style=='arrow-both'){
idEnd=markers[0].id
}
if(idStart.length>0){
idStart="url(#"+idStart+")";
}
if(idEnd.length>0){
idEnd="url(#"+idEnd+")";
}
var subject=this.getShapeSubject(shape);
subject.setAttributeNS(null,"marker-start",idStart);
subject.setAttributeNS(null,"marker-end",idEnd);
}
/**
*getLineStyle
**/
SVGRenderer.prototype.getLineStyle=function(shape){
if(!this.isConnector(shape))return '';
var subject=this.getShapeSubject(shape);
var markerEnd=subject.getAttributeNS(null,"marker-end");
var markerStart=subject.getAttributeNS(null,"marker-start");
if(markerEnd.length>0&&markerStart.length>0)
return "arrow-both";
else if(markerEnd.length==0&&markerStart.length>0)
return "arrow-from";
else if(markerEnd.length>0&&markerStart.length==0)
return "arrow-to";
else
return "none";
}
/**
* get the line dash style
* @return one of -"solid", "short-dash","long-dash"
*/
SVGRenderer.prototype.getLineDashStyle=function(shape){
var subject=this.getShapeSubject(shape);
var dashStyle=subject.getAttributeNS(null,"stroke-dasharray");
if(!dashStyle||dashStyle=="")return "solid";
else if(dashStyle==this.LONG_DASH)return "long-dash";
else return "short-dash";
}
/**
* set the line dash style, we will set this on all
*/
SVGRenderer.prototype.setLineDashStyle=function(shape,style){
if(style=="long-dash")style=this.LONG_DASH;
else if(style=="short-dash")style=this.SHORT_DASH;
else style="";
if(this.isConnector(shape)){
var subject=this.getShapeSubject(shape);
subject.setAttributeNS(null,"stroke-dasharray",style)
}
else{
var subShapes=this.getAllSubShapes(shape)
for(var i=0;i<subShapes.length;i++){
subShapes[i].setAttributeNS(null,"stroke-dasharray",style);
}
}
}
/**
*this method will return the actual subject of a shape, the subject could either be a path or line,polyline in case
of connectors, this assumes that the shape has only one subject
**/
SVGRenderer.prototype.getShapeSubject=function(shape){
if(!shape)return null;
if(this.isConnector(shape)){
var type=this.getConnectorType(shape);
if(type=='line')
return shape.getElementsByTagName('line')[0];
else if(type=='ortho-line')
return shape.getElementsByTagName('polyline')[0];
else if(type=='curve-line')
return shape.getElementsByTagName('path')[0];
}
else if(shape.getElementsByTagName("path").length>0){
return shape.getElementsByTagName("path")[0];
}
//otherwise its a primitive shape e.g rect
else{
return shape;
}
}
/**
* return all the subshapes for a given shape
* @param shape
* @return list of all subshapes
*/
SVGRenderer.prototype.getAllSubShapes=function(shape){
if(!shape)return null;
else return shape.getElementsByTagName("path");
};
/**
*get x:
**/
SVGRenderer.prototype.setX=function(shape,x){
if(shape){
var svg=shape.getElementsByTagName("svg")[0];
if(svg){
svg.setAttributeNS(null, 'x',x+'px');
}
}
}
/**
* get the x value
**/
SVGRenderer.prototype.getX=function(shape,x){
if(shape){
var svg=shape.getElementsByTagName("svg")[0];
if(svg){
var x=svg.getAttribute("x");
return x.split('px')[0];
}
}
}
SVGRenderer.prototype.getY=function(shape,x){
if(shape){
var svg=shape.getElementsByTagName("svg")[0];
if(svg){
var y=svg.getAttribute("y");
return y.split('px')[0];
}
}
}
SVGRenderer.prototype.setY=function(shape,y){
if(shape){
var svg=shape.getElementsByTagName("svg")[0];
if(svg){
svg.setAttributeNS(null, 'y',y+'px');
}
}
}
/**
*set the width, we take the template path and take every x element and multiply it with
*the corresponding template.x/this.COORD_X
**/
SVGRenderer.prototype.setWidth=function(shape,width){
if(shape){
//first set the width in the svg element
shape.getElementsByTagName("svg")[0].setAttributeNS(null,"width",width);
//take tuples of paths and set width on them
var paths=shape.getElementsByTagName("path");
for (var i=0;i<(paths.length/2);i++){
var index=i*2;
this.setPathWidth(paths[index],paths[(index*1)+1],width);
}
}
}
/**
* private method to set the path width
*
*/
SVGRenderer.prototype.setPathWidth=function(path,template,width){
var pathSegList=path.pathSegList;
var tempSegList=template.pathSegList;
//these should match
for(var i=0;i<pathSegList.numberOfItems;i++){
var pathItem=pathSegList.getItem(i);
var pathType=pathItem.pathSegTypeAsLetter;
var tempItem=tempSegList.getItem(i);
pathItem.x=(width)*(tempItem.x/this.COORD_X);
if(pathType=='M'||pathType=='L')continue;
if(pathType=='A'){
pathItem.r1=(width)*(tempItem.r1/this.COORD_X);
continue;
}
if(pathType=='C'){
pathItem.x1=(width)*(tempItem.x1/this.COORD_X);
pathItem.x2=(width)*(tempItem.x2/this.COORD_X);
continue;
}
}
}
/**
**set the height, we take the template path and take every x element and multiply it with
*the corresponding template.x/this.COORD_X
**/
SVGRenderer.prototype.getWidth=function(shape,width){
if(shape){
return shape.getElementsByTagName("svg")[0].getAttributeNS(null,"width");
}
}
/**
*set the height, not sure if this is the correct way to access the matrix elements
**/
SVGRenderer.prototype.setHeight=function(shape,height){
if(shape){
//first set the width in the svg element
shape.getElementsByTagName("svg")[0].setAttributeNS(null,"height",height);
var paths=shape.getElementsByTagName("path");
for (var i=0;i<(paths.length/2);i++){
var index=i*2;
this.setPathHeight(paths[index],paths[(index*1)+1],height);
}
}
}
/**
* private method to set path height
*/
SVGRenderer.prototype.setPathHeight=function(path,template,height){
var pathSegList=path.pathSegList;
var tempSegList=template.pathSegList;
//these should match
for(var i=0;i<pathSegList.numberOfItems;i++){
var pathItem=pathSegList.getItem(i);
var tempItem=tempSegList.getItem(i);
var pathType=pathItem.pathSegTypeAsLetter;
pathItem.y=(height)*(tempItem.y/this.COORD_Y);
if(pathType=='M'||pathType=='L')continue;
if(pathType=='A'){
pathItem.r2=(height)*(tempItem.r2/this.COORD_Y);
continue;
}
if(pathType=='C'){
pathItem.y1=(height)*(tempItem.y1/this.COORD_Y);
pathItem.y2=(height)*(tempItem.y2/this.COORD_Y);
continue;
}
}
}
/**
*get the height, not sure if this is the correct way to access the matrix elements
**/
SVGRenderer.prototype.getHeight=function(shape,height){
if(shape){
return shape.getElementsByTagName("svg")[0].getAttributeNS(null,"height");
}
}
/**
* get the rotation, the rotation is available set at the shape level itelf (g)
**/
SVGRenderer.prototype.getRotation=function(shape){
if(!shape)return null;
var item=shape.transform.baseVal.getItem(0);
return item.angle;
}
/**
*get the center x point of the shape
**/
SVGRenderer.prototype.getCenterX=function(shape){
var box=this.bounds(shape);
return (box.x*1)+((box.width*1)/2);
}
/**
*get the center y point of the shape
**/
SVGRenderer.prototype.getCenterY=function(shape){
var box=this.bounds(shape);
return (box.y*1)+((box.height*1)/2);
}
/**
* set the rotation to be the center of the shape
**/
SVGRenderer.prototype.setRotation=function(shape,angle){
if(!shape)return null;
var box=this.bounds(shape);
var centerX=(box.x*1)+((box.width/2)*1);
var centerY=(box.y*1)+((box.height/2)*1);
var translate="rotate("+angle+","+ centerX+","+centerY+")";
shape.setAttributeNS(null,'transform',translate);
var item=shape.transform.baseVal.getItem(0);
item.matrix.rotate(angle);
}
/**
*a utility function to update rotation of the shape after a reset in x,y,width or height
**/
SVGRenderer.prototype.updateRotation=function(shape){
var angle=this.getRotation(shape);
this.setRotation(shape,angle);
}
/**
*set the shape cursor
**/
SVGRenderer.prototype.setCursor=function(shape,cursor){
if(cursor=='move'||cursor=='resize'||cursor=='crosshair')
shape.style.cursor=cursor;
else
shape.style.cursor="URL("+cursor+"),auto";
}
/************************************END SHAPE ATTRIBUTE GETTERS AND SETTERS********************/
/****************************BEGIN SHAPE MANIPULATION FUNCTIONS(MOVE,RESIZE,ROTATE)************/
/**
*rotate method called from editor
**/
SVGRenderer.prototype.rotate=function(shape,rotation){
if(!rotation){
rotation=0;
}
rotation=rotation%360;
if(rotation<0){
rotation=360+rotation;
}
this.setRotation(shape,rotation);
}
/**
*respond to move keys
**/
SVGRenderer.prototype.fineMove = function(shape, move, isHorizontal) {
//todo fix for line!!!
if(!shape||this.isConnector(shape))return;
if(isHorizontal){
var left=this.getX(shape);
left=(left*1)+move;
this.setX(shape,left);
}
else{
var top=this.getY(shape);
top=(top*1)+move;
this.setY(shape,top);
}
this.updateRotation(shape);
};
/**
*respond to shift+R and shift+L
**/
SVGRenderer.prototype.fineRotateSelection=function(shape,angle){
if(this.isConnector(shape))return;
var rotation=this.getRotation(shape);
if(!rotation)
rotation=0;
var rotation=rotation+angle;
rotation=rotation%360;
if(rotation<0){
rotation=360+rotation;
}
this.setRotation(shape,rotation);
};
SVGRenderer.prototype.remove = function(shape) {
if(shape)
shape.parentNode.removeChild(shape);
}
/**
* move the shape based on mouse movement
**/
SVGRenderer.prototype.move = function(shape, left, top) {
this.setX(shape,left);
this.setY(shape,top);
this.updateRotation(shape);
};
/**
*resize height:
**/
/**
*this resize is called during draw,
*after the draw is complete, subsequent resizes are handled by resizewidth or resizeheight
**/
SVGRenderer.prototype.resize = function(shape, fromX, fromY, toX, toY) {
var deltaX = toX - fromX;
var deltaY = toY - fromY;
if (this.isConnector(shape)) {
var type=this.getConnectorType(shape);
if(type=='line'){
this.setLineTo(shape,toX,toY);
return;
}
else if (type=='ortho-line'){
this.drawOrthoLine(shape,fromX,fromY,toX,toY);
return;
}
else if (type=='curve-line'){
this.drawCurveLine(shape,fromX,fromY,toX,toY,false);
return;
}
}
if (deltaX < 0) {
this.setX(shape,toX);
this.setWidth(shape,-deltaX );
}
else {
this.setWidth(shape,deltaX);
}
if (deltaY < 0) {
this.setY(shape,toY);
this.setHeight(shape,-deltaY );
}
else {
this.setHeight(shape,deltaY);
}
this.updateRotation(shape);
};
/*******************************************BEGIN CURVE CONNECTOR FUNCTIONS***********************************/
SVGRenderer.prototype.drawCurveLine=function(shape,fromX,fromY,toX,toY,resize){
var subject=this.getShapeSubject(shape);
this.setLineFrom(shape,fromX,fromY);
this.setLineTo(shape,toX,toY);
if(!resize){
var x1=Math.abs(fromX-toX);
var y1=Math.abs(fromY-toY);
var cx1=(fromX<toX)?(fromX*1)+(x1*(1/4)):(fromX*1)-(x1*(1/4));
var cx2=(fromX<toX)?(toX*1)-(x1*(1/4)):(toX*1)+(x1*(1/4));
var cy1=(fromY<toY)?(fromY*1)+(y1*(1/4)):(fromY*1)-(y1*(1/4));
var cy2=(fromY<toY)?(toY*1)-(y1*(1/4)):(toY*1)+(y1*(1/4));
this.setControl1(shape,cx1,cy1);
this.setControl2(shape,cx2,cy2);
}
}
/********************************************END CURVE CONNECTOR FUNCTIONS*************************************/
/****************************END SHAPE MANIPULATION FUNCTIONS(MOVE,RESIZE,ROTATE)************/
/**
*command handler for this renderer
**/
SVGRenderer.prototype.editCommand = function(shape, cmd, value,zoom)
{
if (shape != null) {
if(cmd=='sendBack'){
this.sendToBack(shape);
}
else if(cmd=='bringFront'){
this.bringToFront(shape);
}
else if (cmd == 'fillcolor') {
this.setFillColor(shape,value);
}
else if (cmd == 'linecolor') {
this.setLineColor(shape,value);
}
else if (cmd == 'linewidth') {
this.setStrokeWidth(shape, parseInt(value) );
}
else if(cmd=='opacity'){
this.setOpacity(shape,value);
}
else if(cmd=='shadow'){
this.setShadow(shape,value);
}
else if(cmd=='gradient'){
value=(value=='solid')?false:true;
this.setLinearGradient(shape,value);
}
else if(cmd=='linestyle'){
this.setLineStyle(shape,value);
}
else if (cmd=='linedashstyle'){
this.setLineDashStyle(shape,value);
}
else if(cmd=='fontSize'||cmd=='fontFamily'||cmd=='bold'||cmd=='italic'||cmd=='fontColor'||cmd=='align'){
var font=new Object();
font.size='';
font.family='';
font.color='';
font.align='';
font.italics='';
font.bold='';
if(cmd=='fontSize'){
font.size=value;
this.setFont(shape,font,zoom);
}
else if(cmd=='fontFamily'){
font.family=value;
this.setFont(shape,font,zoom);
}
else if(cmd=='bold'){
var oldFont=this.getFont(shape);
if(oldFont.bold=='bold'){
font.bold='normal';
}
else{
font.bold='bold';
}
this.setFont(shape,font);
}
else if(cmd=='italic'){
//debugger;
var oldFont=this.getFont(shape);
if(oldFont.italics=='italic'){
font.italics='normal';
}
else{
font.italics='italic';
}
this.setFont(shape,font);
}
else if(cmd=='fontColor'){
font.color=value;
this.setFont(shape,font);
}
else if(cmd=='align'){
font.align=value;
this.setFont(shape,font);
}
}
}
}
/**
*query handler for this renderer
**/
SVGRenderer.prototype.queryCommand = function(shape, cmd)
{
var result = '';
if (shape != null) {
if (cmd == 'fillcolor') {
return this.getFillColor(shape);
}
else if (cmd == 'linecolor') {
return this.getLineColor(shape);
}
else if (cmd == 'linewidth') {
var width= this.getStrokeWidth(shape);
if(width&&!width.indexOf('px')>=0)
width=width+'px';
return width;
}
else if(cmd=='font'){
return this.getFont(shape);
}
else if(cmd=='linestyle'){
return this.getLineStyle(shape);
}
else if (cmd=='linedashstyle'){
return this.getLineDashStyle(shape);
}
else if(cmd=='opacity'){
return this.getOpacity(shape);
}
else if(cmd=="gradient"){
if(this.getLinearGradient(shape))return 'gradient';
else return 'solid';
}
else if(cmd=="shadow"){
return ""+this.getShadow(shape);
}
}
return result;
}
/*********************************************TRACKER FUNCTIONS***************************************/
/**
*show the line tracker
**/
SVGRenderer.prototype.showLineTracker=function(shape){
var parent=this.loadShape("tracker","g");
this.svgRoot.appendChild(parent);
parent.setAttributeNS(null,"id","tracker-group");
this.updateLineTracker(shape,parent);
return parent;
}
SVGRenderer.prototype.updateLineTracker=function(shape,parent){
var oval=parent.getElementsByTagName("circle")[0];
var type=this.getConnectorType(shape);
if(type=='line'||type=='curve-line'){
var x1=this.getConnectorFromX(shape);
var y1=this.getConnectorFromY(shape);
oval.setAttributeNS(null,"cx",x1);
oval.setAttributeNS(null,"cy",y1);
if(type=='curve-line'){
var line=parent.getElementsByTagName("line")[0];
line.setAttributeNS(null,'x1',x1);
line.setAttributeNS(null,'y1',y1);
}
}
else if (type=='ortho-line'){
var polyline=this.getShapeSubject(shape);
var points=polyline.points;
var x1=points.getItem(0).x;
var y1=points.getItem(0).y;
oval.setAttributeNS(null,"cx",x1);
oval.setAttributeNS(null,"cy",y1);
}
oval.style.zIndex=this.maxIndex+1;
oval=parent.getElementsByTagName("circle")[1];
if(type=='line'||type=='curve-line'){
var x2=this.getConnectorToX(shape);
var y2=this.getConnectorToY(shape);;
oval.setAttributeNS(null,"cx",x2);
oval.setAttributeNS(null,"cy",y2);
if(type=='curve-line'){
var line=parent.getElementsByTagName("line")[1];
line.setAttributeNS(null,'x1',x2);
line.setAttributeNS(null,'y1',y2);
}
}
else if (type=='ortho-line'){
var polyline=this.getShapeSubject(shape);
var points=polyline.points;
var length=points.numberOfItems;
if(length==0)return;
var x2=points.getItem(length-1).x;
var y2=points.getItem(length-1).y;
oval.setAttributeNS(null,"cx",x2);
oval.setAttributeNS(null,"cy",y2);
}
if(type=='curve-line'){
var control1=this.getControl1(shape);
oval=parent.getElementsByTagName("circle")[2];
oval.setAttributeNS(null,"cx",control1.x);
oval.setAttributeNS(null,"cy",control1.y);
oval.style.visibility="visible";
var line=parent.getElementsByTagName("line")[0];
line.setAttributeNS(null,'x2',control1.x);
line.setAttributeNS(null,'y2',control1.y);
var control2=this.getControl2(shape);
oval=parent.getElementsByTagName("circle")[3];
oval.setAttributeNS(null,"cx",control2.x);
oval.setAttributeNS(null,"cy",control2.y);
oval.style.visibility="visible";
line=parent.getElementsByTagName("line")[1];
line.setAttributeNS(null,'x2',control2.x);
line.setAttributeNS(null,'y2',control2.y);
}
oval.style.zIndex=this.maxIndex+1;
//now set the tracker
}
/**
*load the tracker and show it, we may want to cache the tracker if it becomes a performance issue
**/
SVGRenderer.prototype.showTracker = function(shape) {
if(!shape)return
var tracker = $('tracker-group');
if (tracker) {
this.remove(tracker);
}
if(this.isConnector(shape))
{
return this.showLineTracker(shape);
}
tracker=this.loadShape("tracker-group","g");
this.svgRoot.appendChild(tracker);
this.updateTracker(shape);
return tracker;
}
/**
*update the tracker if its already present
**/
SVGRenderer.prototype.updateTracker=function(shape){
if(!shape)return;
var tracker=$('tracker-group');
if(tracker){
if(this.isConnector(shape))
return this.updateLineTracker(shape,tracker);
}
if(!$('tracker-group'))return this.showTracker(shape);
var box=this.bounds(shape);
var trackerGroup=$('tracker-group');
var tracker=$('tracker');
var width=(parseInt(box.width)+10);
var height=(parseInt(box.height)+10);
var x=(parseInt(box.x)-5);
var y=(parseInt(box.y)-5);
var centerX=(x*1)+(width/2);
var centerY=(y*1)+(height/2);
var translate="rotate("+box.rotation+","+ centerX+","+centerY+")";
trackerGroup.setAttributeNS(null,'transform',translate);
tracker.setAttributeNS(null,'width',width+'px');
tracker.setAttributeNS(null,'height',height+'px');
tracker.parentNode.setAttributeNS(null,'x',x+'px');
tracker.parentNode.setAttributeNS(null,'y',y+'px');
$('resize-left').setAttributeNS(null,'y',(box.height/2)+'px');
$('resize-top').setAttributeNS(null,'x',(box.width/2)+'px');
var resizeBottom=$('resize-bottom');
resizeBottom.setAttributeNS(null,'x',(box.width/2)+'px');
resizeBottom.setAttributeNS(null,'y',(parseInt(box.height)+5)+'px');
var resizeRight=$('resize-right');
resizeRight.setAttributeNS(null,'x',(parseInt(box.width)+5)+'px');
resizeRight.setAttributeNS(null,'y',(box.height/2)+'px');
$('tracker-rotate').setAttributeNS(null,'cx',((box.width/2)+5)+'px');
//set the rotation
}
/**************************************END TRACKER FUNCTIONS*****************************************/
/***************************************BEGIN TEXT FUNCTIONS****************************************/
/**
*note:some text functions are inherited from abstractRenderer (see vmlrenderer.js)
**/
/**
*this method should be called only after getShapeText has been called by the editor to save the text
*/
SVGRenderer.prototype.clearShapeText=function(shape){
var nodes=shape.getElementsByTagName("text");
var nodeArray=$A(nodes);
for(var i=0;i<nodeArray.length;i++){
var node=nodeArray[i];
if(node.id=="text:normal"||node.id=="text:newline")
this.remove(node);
}
if(this.isConnector(shape)){
var bgShape=shape.getElementsByTagName("rect");
if(bgShape.length>0){
this.hideConnectorBackground(bgShape[0]);
}
}
}
/**
* basically call to handleTextLinePositioning for svg, since text is handled in the same manner for connectors and shapes,
* the vml versio is implemented
* @see vmlrenderer.js#handleConnectorTextLinePositioning
*/
SVGRenderer.prototype.handleConnectorTextLinePositioning=function(height,width,x,y,center,fontSize,lines,shapeFont,shape){
return this.handleTextLinePositioning(height,width,x,y,center,fontSize,lines,shapeFont,shape);
}
/**
*create the text elements and handle text positioning
**/
SVGRenderer.prototype.handleTextLinePositioning=function(height,width,x,y,center,fontSize,lines,shapeFont,shape){
var centerY=(y*1)+(height*1)/2;
var align;
if(shapeFont.align=='center'){
align=(x*1)+(width/2);
}
else if(shapeFont.align=='left'){
align=(x*1)+(10*1)
}
else{
align=(x*1)+(width-10);
}
var shapeArray=new Array();
for (var i=center;i>0;i--){
var lineTopMargin=(centerY)+((fontSize*1.1)*(i-center));
lineTopMargin=(lineTopMargin*1)+((fontSize)/4);
shapeArray[shapeArray.length]=this.createTextShape(lines[i-1],true,lineTopMargin,null,align,null,shapeFont,shape);
}
for (var i=center;i<lines.length;i++){
var lineTopMargin=(centerY)+((fontSize*1.1)*(i+1-center));
lineTopMargin=(lineTopMargin*1)+((fontSize)/4);
shapeArray[shapeArray.length]=this.createTextShape(lines[i],true,lineTopMargin,null,align,null,shapeFont,shape);
}
return shapeArray;
}
/**
* set the dimensions of the background shape for the connector text
* todo, fix visibility here...
*/
SVGRenderer.prototype.handleConnectorTextBackgroundPositioning=function(shape,rect,text){
var bgShape=this.getConnectorBackgroundShape(shape);
shape.getElementsByTagName("svg")[0].appendChild(bgShape);
if(text&&trim(text).length>0){
bgShape.setAttributeNS(null,"fill","white");
bgShape.setAttributeNS(null,"x",rect.x);
bgShape.setAttributeNS(null,"y",rect.y);
bgShape.setAttributeNS(null,"width",rect.width);
bgShape.setAttributeNS(null,"height",rect.height);
}
else{
this.hideConnectorBackground(bgShape);
}
}
/**
* hide the connector background, this comes handy when we want to clear the connector text (during moves, resize etc)
* or when the text is empty
* @param background shape for the connector
*/
SVGRenderer.prototype.hideConnectorBackground=function(bgShape){
if(bgShape){
bgShape.setAttributeNS(null,"x",0);
bgShape.setAttributeNS(null,"y",0);
bgShape.setAttributeNS(null,"width",0);
bgShape.setAttributeNS(null,"height",0);
}
}
/**
* a utility function to create a text set, sometimes we may need to create a dummy text set (which can hold the
*default values for font etc. (see setShapeText)in which case
* we need to pass the shape.id as the type in the line object and texpathok=false
*/
SVGRenderer.prototype.createTextShape=function(line,textpathok,lineTopMargin,lineHeightMargin,start,end,shapeFont,containerShape){
var shape=null;
if(!textpathok){
shape=containerShape.ownerDocument.getElementById("text:template"+line.type);
}
if(textpathok||!shape){
shape=this.createElement("text",this.svgNamespace);
if(textpathok)
shape.id="text:"+line.type;
else
shape.id="text:template"+line.type;
}
shape.setAttributeNS(null,"x",start);
shape.setAttributeNS(null,"y",lineTopMargin);
shape.style.position="absolute";
shape.setAttributeNS(null,"fill",shapeFont.color);
shape.setAttributeNS(null,"font-size",shapeFont.size);
shape.setAttributeNS(null,"font-weight",shapeFont.bold);
shape.setAttributeNS(null,"font-family",shapeFont.family);
shape.setAttributeNS(null,"font-style",shapeFont.italics);
//directive to preserve any space
shape.setAttribute("xml:space","preserve");
var textAnchor="middle";
if(shapeFont.align=='left'){
textAnchor="start";
}
else if(shapeFont.align=='right'){
textAnchor="end";
}
shape.setAttributeNS(null,"text-anchor",textAnchor);
shape.textContent=line.text;
return shape;
}
/**
*utility function to set the fontsize,fontcolor,fontfamily,fontdecoration(bold,italics,underline) and textalign for a given shape
* if you want to selectively set something e.g size, then only pass size in the font leaving the rest of the stuff as null
*/
SVGRenderer.prototype.setFont=function(shape,font,zoom){
var dummyText=this.getShapeText(shape);
//if this is null, then dummy text does not exist
//so we have to create one and then we leave
if(!dummyText){
this.fillUpFont(font);
this.setShapeText(shape," ",font,true,null,zoom);
return;
}
//we already have text...now we can start, get the text shapes first
var textList=shape.getElementsByTagName("text");
var shapeFont=this.getFont(shape);
//if font size changes, we really need to redo the spacing etc.
if(font.size!=''&&(font.size!=shapeFont.size)){
this.clearShapeText(shape);
this.setShapeText(shape,dummyText,font,true,shapeFont,zoom);
}
//otherwise we will set things individually, no need to create things
if(font.color!=''){
for(var i=0;i<textList.length;i++){
textList[i].setAttributeNS(null,"fill",font.color);
}
}
//now set the text path specific properties
if(font.family!=''){
for(var i=0;i<textList.length;i++){
textList[i].setAttributeNS(null,"font-family",font.family);
}
}
if(font.bold!=''){
for(var i=0;i<textList.length;i++){
textList[i].setAttributeNS(null,"font-weight",font.bold);
}
}
if(font.italics!=''){
for(var i=0;i<textList.length;i++){
textList[i].setAttributeNS(null,"font-style",font.italics);
}
}
if(font.align!=''){
var align;
//pass dummytext and zoom for connectors
var rect=this.getTextBounds(shape,dummyText,zoom);
var x=rect['x'];
var width=rect['width'];
if(font.align=='center'){
align=(x*1)+(width/2);
}
else if(font.align=='left'){
align=(x*1)+(10*1)
}
else{
align=(x*1)+(width-10);
}
var textAnchor="middle";
if(font.align=='left'){
textAnchor="start";
}
else if(font.align=='right'){
textAnchor="end";
}
for(var i=0;i<textList.length;i++){
textList[i].setAttributeNS(null,"x",align);
textList[i].setAttributeNS(null,"text-anchor",textAnchor);
}
}
}
/**
*this method will pull out the font from the dummyText and then report it back
**/
SVGRenderer.prototype.getFont=function(shape){
var font=new Object();
font.size='';
font.family='';
font.color='';
font.align='';
font.italics='';
font.bold='';
//for backward compatibility. after 0.2 we will use "text:template";
var element=document.getElementById("text:dummy"+shape.id);;
if(!element){
element=document.getElementById("text:template"+shape.id);
}
if(!element)
return font;
else{
font.color=element.getAttributeNS(null,"fill");
font.family=element.getAttributeNS(null,"font-family");
font.size=element.getAttributeNS(null,"font-size");
font.bold=element.getAttributeNS(null,"font-weight");
font.italics=element.getAttributeNS(null,"font-style");;
//todo for align!!!
var align=element.getAttributeNS(null,"text-anchor");
if(align=='middle')
align='center';
else if(align=='end')
align='right';
else
align='left';
font.align=align;
}
return font;
}
SVGRenderer.prototype.getMarkup = function() {
return this.container.innerHTML;
}
/**incase of svg the selection source comes back as path which resides in g/svg/path,
**in order to return g we need to climb 2 levels
**/
SVGRenderer.prototype.getShapeFromEventSource=function(source){
if(source){
if(source.tagName=='text')
return source.parentNode;
else
return source.parentNode.parentNode;
}
}
/**
*append an attribute to the page cumulate draw specific
**/
SVGRenderer.prototype.appendPageAttribute=function(div,attribute){
if(div){
var svg=div.getElementsByTagName("svg")[0];
svg.appendChild(attribute);
}
}
/**
*get the actual data from within the richdraw div
**/
SVGRenderer.prototype.getRealData=function(){
var xml=this.svgRoot.xml;
var parser=new DOMParser(true);
parser.preserveWhiteSpace=true;
return parser.parseFromString(xml, "application/xml");
}
/**
*return the response as a valid xml document
**/
SVGRenderer.prototype.getValidDocumentFromResponse=function(response){
var parser=new DOMParser(true);
parser.preserveWhiteSpace=true;
return parser.parseFromString(response, "application/xml");
}
/**
*open the objects in .fmd file
**/
SVGRenderer.prototype.open=function(div){
var nodes=div.getElementsByTagName("g");
nodes=$A(nodes);
for(var i=0;i<nodes.length;i++){
this.svgRoot.appendChild(nodes[i]);
}
}